package top.zhangjianyong.tools.etf;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import top.zhangjianyong.tools.entity.ETF;
import top.zhangjianyong.tools.entity.ETFData;
import top.zhangjianyong.tools.service.mybatis.IETFDataService;
import top.zhangjianyong.tools.service.mybatis.IETFService;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @author ： zhangjianyong
 * @date ： 2022/12/22 4:29 PM
 */
@Data
@Slf4j
public class ETFManager {

    //手上剩余钱
    private BigDecimal haveMoney;
    private LocalDate start;
    private LocalDate current;
    private LocalDate end;

    private List<String> logList = new ArrayList<>();


    private IETFService ietfService;
    private IETFDataService ietfDataService;

    private ETFHolder etfHold = new ETFHolder();

    private List<ETF> list;
    private int hc;
    private int sy;
    private int day;
    private int moneyLevel;

    public ETFManager(BigDecimal haveMoney, LocalDate start, LocalDate end, int day, int hc, int sy,
                      int moneyLevel,
                      IETFService ietfService, IETFDataService ietfDataService) {
        this.haveMoney = haveMoney;
        this.moneyLevel = moneyLevel;
        this.day = day;
        this.hc = hc;
        this.sy = sy;
        this.start = start;
        current = start;
        this.end = end;
        this.ietfDataService = ietfDataService;
        this.ietfService = ietfService;


    }

    public void init() {
        //取出所有的数据
        this.list = ietfService.listNotDel();
        //取出每日数据
        this.list.forEach(etf -> {
            List<ETFData> etfDataList = ietfDataService.listByCode(etf.getCode());
            this.etfHold.putDateMap(etf.getCode(), etfDataList);
        });
    }

    public void process() {

        while (current.isBefore(end)) {
            log.info("当前日期：{}", current);
            //处理每一天的交易
            if (!new ETFProcess(current, list, this, day, hc, sy).process()) {
                log.info("钱不够了");
                //break;
            }

            current = current.plusDays(1);
        }
        //最终结果
        AtomicReference<BigDecimal> total = new AtomicReference<>(this.haveMoney);
        print("剩余资产：");
        print("现金：" + this.haveMoney);

        Map<String, ETFHoldInfo> etf_hold_map = this.etfHold.getETF_HOLD_MAP();
        etf_hold_map.forEach((k, v) -> {
            ETF etf = v.getEtf();
            total.set(total.get().add(v.getTotalMoney()));
            print("基金：" + etf.getCode() + "-" + etf.getName() + " 份额：" + v.getUnit()
                    + " 价值：" + v.getTotalMoney() + " 购入价：" + v.getBuyMoney());
        });

        print("总价值：" + total.get());
    }


    public boolean buy(LocalDate date, BigDecimal money, ETF etf, int num) {
        if (this.haveMoney.compareTo(money) > 0) {

            this.haveMoney = this.haveMoney.subtract(money);
            this.etfHold.putETF(etf, money, new BigDecimal(num));
            print("购入：" + date + "，" + etf.getCode() + "-" + etf.getName() + "," + money + ", 剩余：" + this.haveMoney);
            return true;
        }
        print("钱不够：" + date + " 剩余：" + this.haveMoney);

        return false;

    }

    public boolean isLowMoney() {
        return this.haveMoney.compareTo(new BigDecimal(moneyLevel)) < 0;
    }

    public void sell(LocalDate date, ETF etf, BigDecimal value) {
        String code = etf.getCode();
        ETFHoldInfo etfHoldInfo = this.etfHold.getETF(code);
        BigDecimal unit = etfHoldInfo.getUnit();

        BigDecimal totalMoney = unit.multiply(value);
        log.info("出售收入：{},{}", code, totalMoney);
        haveMoney = haveMoney.add(totalMoney);
        etfHoldInfo.setUnit(BigDecimal.ZERO);
        etfHoldInfo.setBuyMoney(BigDecimal.ZERO);
        this.etfHold.putETF(code, etfHoldInfo);
        print("出售：" + date + "，" + etf.getCode() + "-" + etf.getName() + "," + totalMoney + ", 剩余：" + this.haveMoney);
    }


    public void print(String log) {
        logList.add(log);
    }
}
